Domain0 identifies IOAPIC by physical base address rather than BIOS-assigned identifier.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 3 Mar 2006 14:05:25 +0000 (15:05 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 3 Mar 2006 14:05:25 +0000 (15:05 +0100)
This seems a more reliable method since it seems that we always trust the base address
and we don't need to work around renumbering/rebasing as we do with APICIDs.

This is an alternative to the Yonah networking patch from Allen Kay at Intel.

Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c
linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c
xen/arch/x86/io_apic.c
xen/arch/x86/physdev.c
xen/include/public/physdev.h

index 003300858a72e7a71c2a3ed68b84d720a0263e77..53704a58d794052f37cd261b009e2f17091d89aa 100644 (file)
@@ -61,8 +61,8 @@ static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
        int ret;
 
        op.cmd = PHYSDEVOP_APIC_READ;
-       op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
-       op.u.apic_op.offset = reg;
+       op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+       op.u.apic_op.reg = reg;
        ret = HYPERVISOR_physdev_op(&op);
        if (ret)
                return ret;
@@ -74,8 +74,8 @@ static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsign
        physdev_op_t op;
 
        op.cmd = PHYSDEVOP_APIC_WRITE;
-       op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
-       op.u.apic_op.offset = reg;
+       op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+       op.u.apic_op.reg = reg;
        op.u.apic_op.value = value;
        HYPERVISOR_physdev_op(&op);
 }
index 5d51a7f3b7c9830f953e428f0f79186e95b83ff8..fd72947df79165eb758575256400dec225d37a47 100644 (file)
@@ -108,8 +108,8 @@ static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
        int ret;
 
        op.cmd = PHYSDEVOP_APIC_READ;
-       op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
-       op.u.apic_op.offset = reg;
+       op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+       op.u.apic_op.reg = reg;
        ret = HYPERVISOR_physdev_op(&op);
        if (ret)
                return ret;
@@ -121,8 +121,8 @@ static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsign
        physdev_op_t op;
 
        op.cmd = PHYSDEVOP_APIC_WRITE;
-       op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
-       op.u.apic_op.offset = reg;
+       op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+       op.u.apic_op.reg = reg;
        op.u.apic_op.value = value;
        HYPERVISOR_physdev_op(&op);
 }
index aef5d64b5a790a7fe3dcac917f0e2cf5942860fc..e71603c1257da8f127eaf6fdaff7028241950c8e 100644 (file)
@@ -1634,16 +1634,6 @@ static inline void check_timer(void)
           "report.  Then try booting with the 'noapic' option");
 }
 
-#define NR_IOAPIC_BIOSIDS 256
-static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS];
-static void store_ioapic_biosid_mapping(void)
-{
-    u8 apic;
-    memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS);
-    for ( apic = 0; apic < nr_ioapics; apic++ )
-        ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic;
-}
-
 /*
  *
  * IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1655,8 +1645,6 @@ static void store_ioapic_biosid_mapping(void)
 
 void __init setup_IO_APIC(void)
 {
-    store_ioapic_biosid_mapping();
-
     enable_IO_APIC();
 
     if (acpi_ioapic)
@@ -1840,50 +1828,45 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 
 #endif /*CONFIG_ACPI_BOOT*/
 
+static int ioapic_physbase_to_id(unsigned long physbase)
+{
+    int apic;
+    for ( apic = 0; apic < nr_ioapics; apic++ )
+        if ( mp_ioapics[apic].mpc_apicaddr == physbase )
+            return apic;
+    return -EINVAL;
+}
 
-int ioapic_guest_read(int apicid, int address, u32 *pval)
+int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
 {
-    u32 val;
-    int apicenum;
-    union IO_APIC_reg_00 reg_00;
+    int apic;
     unsigned long flags;
 
-    if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
-         ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
-        return -EINVAL;
+    if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
+        return apic;
 
     spin_lock_irqsave(&ioapic_lock, flags);
-    val = io_apic_read(apicenum, address);
+    *pval = io_apic_read(apic, reg);
     spin_unlock_irqrestore(&ioapic_lock, flags);
 
-    /* Rewrite APIC ID to what the BIOS originally specified. */
-    if ( address == 0 )
-    {
-        reg_00.raw = val;
-        reg_00.bits.ID = apicid;
-        val = reg_00.raw;
-    }
-
-    *pval = val;
     return 0;
 }
 
-int ioapic_guest_write(int apicid, int address, u32 val)
+int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
 {
-    int apicenum, pin, irq;
+    int apic, pin, irq;
     struct IO_APIC_route_entry rte = { 0 };
     struct irq_pin_list *entry;
     unsigned long flags;
 
-    if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
-         ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
-        return -EINVAL;
+    if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
+        return apic;
 
     /* Only write to the first half of a route entry. */
-    if ( (address < 0x10) || (address & 1) )
+    if ( (reg < 0x10) || (reg & 1) )
         return 0;
     
-    pin = (address - 0x10) >> 1;
+    pin = (reg - 0x10) >> 1;
 
     *(u32 *)&rte = val;
     rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
@@ -1899,7 +1882,7 @@ int ioapic_guest_write(int apicid, int address, u32 val)
     if ( rte.delivery_mode > dest_LowestPrio )
     {
         printk("ERROR: Attempt to write weird IOAPIC destination mode!\n");
-        printk("       APIC=%d/%d, lo-reg=%x\n", apicid, pin, val);
+        printk("       APIC=%d/%d, lo-reg=%x\n", apic, pin, val);
         return -EINVAL;
     }
 
@@ -1924,19 +1907,19 @@ int ioapic_guest_write(int apicid, int address, u32 val)
         /* Record the pin<->irq mapping. */
         for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] )
         {
-            if ( (entry->apic == apicenum) && (entry->pin == pin) )
+            if ( (entry->apic == apic) && (entry->pin == pin) )
                 break;
             if ( !entry->next )
             {
-                add_pin_to_irq(irq, apicenum, pin);
+                add_pin_to_irq(irq, apic, pin);
                 break;
             }
         }
     }
 
     spin_lock_irqsave(&ioapic_lock, flags);
-    io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0));
-    io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1));
+    io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0));
+    io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1));
     spin_unlock_irqrestore(&ioapic_lock, flags);
 
     return 0;
index 418392da9250a0e2d1c8ca74c0b3e506b922a7b0..c3baee8572ab07a290a2cefa323a980d1875936c 100644 (file)
 #include <public/xen.h>
 #include <public/physdev.h>
 
-extern int ioapic_guest_read(int apicid, int address, u32 *pval);
-extern int ioapic_guest_write(int apicid, int address, u32 pval);
+extern int
+ioapic_guest_read(
+    unsigned long physbase, unsigned int reg, u32 *pval);
+extern int
+ioapic_guest_write(
+    unsigned long physbase, unsigned int reg, u32 pval);
 
 /*
  * Demuxing hypercall.
@@ -49,7 +53,9 @@ long do_physdev_op(struct physdev_op *uop)
         if ( !IS_PRIV(current->domain) )
             break;
         ret = ioapic_guest_read(
-            op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value);
+            op.u.apic_op.apic_physbase,
+            op.u.apic_op.reg,
+            &op.u.apic_op.value);
         break;
 
     case PHYSDEVOP_APIC_WRITE:
@@ -57,7 +63,9 @@ long do_physdev_op(struct physdev_op *uop)
         if ( !IS_PRIV(current->domain) )
             break;
         ret = ioapic_guest_write(
-            op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value);
+            op.u.apic_op.apic_physbase,
+            op.u.apic_op.reg,
+            op.u.apic_op.value);
         break;
 
     case PHYSDEVOP_ASSIGN_VECTOR:
index 9124ca54744de8ae9d988877fd157db9dc81f8fc..b9486d5fa9eb2de67901c8bb94c67d114e1bec1c 100644 (file)
@@ -33,8 +33,8 @@ typedef struct physdevop_set_iobitmap {
 
 typedef struct physdevop_apic {
     /* IN */
-    uint32_t apic;
-    uint32_t offset;
+    unsigned long apic_physbase;
+    uint32_t reg;
     /* IN or OUT */
     uint32_t value;
 } physdevop_apic_t;